package ph.com.gs3.formalistics.presenter;

import java.util.ArrayList;
import java.util.List;

import ph.com.gs3.formalistics.R;
import ph.com.gs3.formalistics.global.utilities.logging.FLLogger;
import ph.com.gs3.formalistics.model.valueobjects.business.MessageThread;
import ph.com.gs3.formalistics.model.valueobjects.business.User;
import ph.com.gs3.formalistics.presenter.adapters.MessengerViewPagerAdapter;
import ph.com.gs3.formalistics.presenter.fragments.views.OnlineUsersViewFragment;
import ph.com.gs3.formalistics.presenter.fragments.views.ThreadListViewFragment;
import ph.com.gs3.formalistics.presenter.fragments.views.OnlineUsersViewFragment.OnlineUsersViewActionListener;
import ph.com.gs3.formalistics.presenter.fragments.views.ThreadListViewFragment.ThreadListViewActionListener;
import ph.com.gs3.formalistics.service.services.FetchMessagesService;
import ph.com.gs3.formalistics.service.services.FullMessagingDataUpdateService;
import ph.com.gs3.formalistics.service.services.GetOnlineUsersService;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;

public class MessengerActivity extends FragmentActivity implements ThreadListViewActionListener,
        OnlineUsersViewActionListener {

	public static final String TAG = MessengerActivity.class.getSimpleName();

	public static final String EXTRA_CURRENT_USER = "current_user";

	private ActionBar actionBar;
	private ViewPager viewPager;

	private User currentUser;
	private boolean messagingDataUpdateServiceBound;

	private MessengerViewPagerAdapter viewPagerAdapter;
	private ThreadListViewFragment threadListViewFragment;
	private OnlineUsersViewFragment onlineUsersViewFragment;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_messenger);

		// Set up the action bar.
		actionBar = getActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		viewPagerAdapter = new MessengerViewPagerAdapter(getSupportFragmentManager());
		viewPager = (ViewPager) findViewById(R.id.Messenger_vpMainViewPager);
		viewPager.setAdapter(viewPagerAdapter);
		viewPager.setOnPageChangeListener(pageChangeListener);

		// For each of the sections in the app, add a tab to the action bar.
		for (int i = 0; i < viewPagerAdapter.getCount(); i++) {
			// Create a tab with text corresponding to the page title defined by
			// the adapter. Also specify this Activity object, which implements
			// the TabListener interface, as the callback (listener) for when
			// this tab is selected.
			actionBar.addTab(actionBar.newTab().setText(viewPagerAdapter.getPageTitle(i))
			        .setTabListener(tabListener));
		}

		// get a reference of the fragments from the adapters
		threadListViewFragment = (ThreadListViewFragment) viewPagerAdapter.getItem(0);
		onlineUsersViewFragment = (OnlineUsersViewFragment) viewPagerAdapter.getItem(1);

		initializeFields();
		startMessagingDataUpdateService();
		registerBroadcastReceivers();

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.messenger, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		unbindServices();
		unregisterReceivers();
	}

	// =================================================================================
	// {{ Functional Methods

	private void initializeFields() {
		Bundle extras = getIntent().getExtras();
		currentUser = (User) extras.getSerializable(EXTRA_CURRENT_USER);
	}

	// }}

	// =================================================================================
	// {{ Navigation Methods

	private void navigateToMessageViewWithUser(User user) {

		Intent intent = new Intent(this, ThreadMessagesActivity.class);
		intent.putExtra(ThreadMessagesActivity.EXTRA_USER, user);
		startActivity(intent);

	}

	private void navigateToMessageViewWithThread(MessageThread messageThread) {

		Intent intent = new Intent(this, ThreadMessagesActivity.class);
		intent.putExtra(ThreadMessagesActivity.EXTRA_THREAD, messageThread);
		startActivity(intent);

	}

	// }}

	// =================================================================================
	// {{ Service Management Methods

	private void startMessagingDataUpdateService() {

		Intent intent = new Intent(MessengerActivity.this, FullMessagingDataUpdateService.class);

		intent.putExtra(FullMessagingDataUpdateService.EXTRA_CURRENT_USER, currentUser);
		messagingDataUpdateServiceBound = bindService(intent, fullDataUpdateServiceConnection,
		        Context.BIND_AUTO_CREATE);
		startService(intent);

		FLLogger.d(TAG, "Full messaging data update service is now started");

	}

	private void registerBroadcastReceivers() {

		IntentFilter onlineUsersIntentFilter = new IntentFilter();

		onlineUsersIntentFilter.addAction(GetOnlineUsersService.ACTION_ON_ERROR);
		onlineUsersIntentFilter.addAction(GetOnlineUsersService.ACTION_ON_ONLINE_USERS_UDPATED);
		onlineUsersIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);

		registerReceiver(getOnlineUsersBroadcastReceiver, onlineUsersIntentFilter);

		// fetch messages

		IntentFilter fetchMessagesIntentFilter = new IntentFilter();

		fetchMessagesIntentFilter.addAction(FetchMessagesService.ACTION_ON_THREADS_FETCHED);
		fetchMessagesIntentFilter
		        .addAction(FetchMessagesService.ACTION_ON_MESSAGES_FOR_THREAD_FETCHED);
		fetchMessagesIntentFilter.addAction(FetchMessagesService.ACTION_ON_ALL_MESSAGES_FETCHED);
		fetchMessagesIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);

		registerReceiver(fetchMessagesBroadcastReceiver, fetchMessagesIntentFilter);

	}

	private void unregisterReceivers() {
		unregisterReceiver(getOnlineUsersBroadcastReceiver);
		unregisterReceiver(fetchMessagesBroadcastReceiver);
	}

	private void unbindServices() {
		if (messagingDataUpdateServiceBound) {
			unbindService(fullDataUpdateServiceConnection);
			messagingDataUpdateServiceBound = false;
			FLLogger.d(TAG, "FullMessagingDataUpdateService unbound");
		}
	}

	// }}

	// ========================================================================
	// {{ Service Connections

	private ServiceConnection fullDataUpdateServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName arg0, IBinder arg1) {
			FLLogger.d(TAG, "Service connected");
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {
			FLLogger.d(TAG, "Service connected");
		}

	};

	// }}

	// =================================================================================
	// {{ Action listeners

	private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {

		@Override
		public void onPageSelected(int index) {
			// display the selected item on the action bar whenever the user
			// swipes to a different page
			actionBar.setSelectedNavigationItem(index);
		}

		@Override
		public void onPageScrollStateChanged(int arg0) {}

		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {}

	};

	private ActionBar.TabListener tabListener = new ActionBar.TabListener() {

		@Override
		public void onTabSelected(Tab tab, FragmentTransaction transaction) {
			viewPager.setCurrentItem(tab.getPosition());
		}

		@Override
		public void onTabReselected(Tab tab, FragmentTransaction transaction) {}

		@Override
		public void onTabUnselected(Tab tab, FragmentTransaction transaction) {}

	};

	// }}

	// =================================================================================
	// {{ Broadcast receivers

	@SuppressWarnings("unchecked")
	private BroadcastReceiver getOnlineUsersBroadcastReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {

			String action = intent.getAction();
			Bundle extras = intent.getExtras();

			if (GetOnlineUsersService.ACTION_ON_ONLINE_USERS_UDPATED.equals(action)) {
				List<User> onlineUsers = (ArrayList<User>) extras
				        .getSerializable(GetOnlineUsersService.EXTRA_ONLINE_USERS);

				onlineUsersViewFragment.setDisplayingUsers(onlineUsers);
			}

		}

	};

	@SuppressWarnings("unchecked")
	private BroadcastReceiver fetchMessagesBroadcastReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {

			String action = intent.getAction();
			Bundle extras = intent.getExtras();

			FLLogger.d(TAG, "Triggered: " + action);

			if (FetchMessagesService.ACTION_ON_THREADS_FETCHED.equals(action)) {

				List<MessageThread> threads = (ArrayList<MessageThread>) extras
				        .getSerializable(FetchMessagesService.EXTRA_FETCHED_THREADS);

				threadListViewFragment.setDisplayingThreads(threads);
			}

		}

	};

	// }}

	// =========================================================================
	// {{ View Implementation Methods

	@Override
	public void onThreadClicked(MessageThread messageThread) {
		navigateToMessageViewWithThread(messageThread);
	}

	@Override
	public void onUserClicked(User user) {
		navigateToMessageViewWithUser(user);
	}

	// }}

}
